﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;

namespace YasharEl.Infrastructure.ExceptionHandling
{
    [ContractClass(typeof(ExceptionManagerContract))]
    public interface IExceptionManager
    {
        bool HandleException(Exception exceptionToHandle, string policyName, out Exception exceptionToThrow);

        bool HandleException(Exception exceptionToHandle, string policyName);

        void Process(Action action, string policyName);

        TResult Process<TResult>(Func<TResult> action, TResult defaultResult, string policyName);
    }

    [ContractClassFor(typeof(IExceptionManager))]
    internal abstract class ExceptionManagerContract : IExceptionManager
    {
        public bool HandleException(Exception exceptionToHandle, string policyName, out Exception exceptionToThrow)
        {
            Contract.Requires<ArgumentNullException>(exceptionToHandle != null, "exceptionToHandle could not be null.");
            Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(policyName), "policyName could not be null or empty.");
            exceptionToThrow = null;
            return default(bool);
        }

        public bool HandleException(Exception exceptionToHandle, string policyName)
        {
            Contract.Requires<ArgumentNullException>(exceptionToHandle != null, "exceptionToHandle could not be null.");
            Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(policyName), "policyName could not be null or empty.");
            return default(bool);
        }

        public void Process(Action action, string policyName)
        {
            Contract.Requires<ArgumentNullException>(action != null, "action could not be null.");
            Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(policyName), "policyName could not be null or empty.");
        }

        public TResult Process<TResult>(Func<TResult> action, TResult defaultResult, string policyName)
        {
            Contract.Requires<ArgumentNullException>(action != null, "action could not be null.");
            Contract.Requires<ArgumentNullException>(defaultResult != null, "defaultResult could not be null.");
            Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(policyName), "policyName could not be null or empty.");
            return default(TResult);
        }
    }
}
